home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1993 March / Nautilus-4-3 / Nautilus-4-3.bin / Multimedia / Feature / RlePict1.1 Folder / lib / Runput.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-08  |  10.7 KB  |  370 lines

  1. /*
  2.  * This software is copyrighted as noted below.  It may be freely copied,
  3.  * modified, and redistributed, provided that the copyright notice is 
  4.  * preserved on all copies.
  5.  * 
  6.  * There is no warranty or other guarantee of fitness for this software,
  7.  * it is provided solely "as is".  Bug reports or fixes may be sent
  8.  * to the author, who may or may not act on them as he desires.
  9.  *
  10.  * You may not include this software in a program or other software product
  11.  * without supplying the source, or without informing the end-user that the 
  12.  * source is available for no extra charge.
  13.  *
  14.  * If you modify this software, you should include a notice giving the
  15.  * name of the person performing the modification, the date of modification,
  16.  * and the reason for such modification.
  17.  *
  18.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  19.  *  to have all "void" functions so declared.
  20.  */
  21. /* 
  22.  * Runput.c - General purpose Run Length Encoding.
  23.  * 
  24.  * Author:    Spencer W. Thomas
  25.  *         Computer Science Dept.
  26.  *         University of Utah
  27.  * Date:    Mon Aug  9 1982
  28.  * Copyright (c) 1982,1986 Spencer W. Thomas
  29.  * 
  30.  * $Id: Runput.c,v 3.0.1.1 1992/01/28 18:17:40 spencer Exp $
  31.  * 
  32.  * Modified by:    Todd W. Fuqua
  33.  *     Date:    Jul 22 1984
  34.  * convert to new RLE format to make room for larger frame buffers
  35.  */
  36.  
  37. /* THIS IS WAY OUT OF DATE.  See rle.5.
  38.  * The output file format is:
  39.  * 
  40.  * Word 0:    A "magic" number.  The top byte of the word contains
  41.  *        the letter 'R' or the letter 'W'.  'W' indicates that
  42.  *        only black and white information was saved.  The bottom
  43.  *        byte is one of the following:
  44.  *    ' ':    Means a straight "box" save, -S flag was given.
  45.  *    'B':    Image saved with background color, clear screen to
  46.  *        background before restoring image.
  47.  *    'O':    Image saved in overlay mode.
  48.  * 
  49.  * Words 1-6:    The structure
  50.  * {     short   xpos,            Lower left corner
  51.  *             ypos,
  52.  *             xsize,            Size of saved box
  53.  *             ysize;
  54.  *     char    rgb[3];            Background color
  55.  *     char    map;            flag for map presence
  56.  * }
  57.  * 
  58.  * If the map flag is non-zero, then the color map will follow as 
  59.  * 3*256 16 bit words, first the red map, then the green map, and
  60.  * finally the blue map.
  61.  * 
  62.  * Following the setup information is the Run Length Encoded image.
  63.  * Each instruction consists of a 4-bit opcode, a 12-bit datum and
  64.  * possibly one or more following words (all words are 16 bits).  The
  65.  * instruction opcodes are:
  66.  * 
  67.  * SkipLines (1):   The bottom 10 bits are an unsigned number to be added to
  68.  *            current Y position.
  69.  * 
  70.  * SetColor (2):    The datum indicates which color is to be loaded with
  71.  *             the data described by the following ByteData and
  72.  *             RunData instructions.  0->red, 1->green, 2->blue.  The
  73.  *             operation also resets the X position to the initial
  74.  *             X (i.e. a carriage return operation is performed).
  75.  * 
  76.  * SkipPixels (3):  The bottom 10 bits are an unsigned number to be
  77.  *             added to the current X position.
  78.  * 
  79.  * ByteData (5):    The datum is one less than the number of bytes of
  80.  *             color data following.  If the number of bytes is
  81.  *             odd, a filler byte will be appended to the end of
  82.  *             the byte string to make an integral number of 16-bit
  83.  *             words.  The bytes are in PDP-11 order.  The X
  84.  *             position is incremented to follow the last byte of
  85.  *             data.
  86.  * 
  87.  * RunData (6):        The datum is one less than the run length.  The
  88.  *             following word contains (in its lower 8 bits) the
  89.  *             color of the run.  The X position is incremented to
  90.  *             follow the last byte in the run.
  91.  */
  92.  
  93. #include    "stdio.h"
  94. #include    "rle_put.h"
  95. #include    "rle.h"
  96. #include    "rle_code.h"
  97.  
  98. #define UPPER 255            /* anything bigger ain't a byte */
  99.  
  100. /*
  101.  * Macros to make writing instructions with correct byte order easier.
  102.  */
  103. /* Write a two-byte value in little_endian order. */
  104. #define    put16(a)    (putc((a)&0xff,rle_fd),putc(((a)>>8)&0xff,rle_fd))
  105.  
  106. /* short instructions */
  107. #define mk_short_1(oper,a1)        /* one argument short */ \
  108.     putc(oper,rle_fd), putc((char)a1,rle_fd)
  109.  
  110. #define mk_short_2(oper,a1,a2)        /* two argument short */ \
  111.     putc(oper,rle_fd), putc((char)a1,rle_fd), put16(a2)
  112.  
  113. /* long instructions */
  114. #define mk_long_1(oper,a1)        /* one argument long */ \
  115.     putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), put16(a1)
  116.  
  117. #define mk_long_2(oper,a1,a2)        /* two argument long */ \
  118.     putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), \
  119.     put16(a1), put16(a2)
  120.  
  121. /* choose between long and short format instructions */
  122. /* NOTE: these macros can only be used where a STATEMENT is legal */
  123.  
  124. #define mk_inst_1(oper,a1)        /* one argument inst */ \
  125.     if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
  126.  
  127. #define mk_inst_2(oper,a1,a2)        /* two argument inst */ \
  128.     if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
  129.  
  130. /* 
  131.  * Opcode definitions
  132.  */
  133. #define        RSkipLines(n)           mk_inst_1(RSkipLinesOp,(n))
  134.  
  135. #define        RSetColor(c)        mk_short_1(RSetColorOp,(c))
  136.                     /* has side effect of performing */
  137.                     /* "carriage return" action */
  138.  
  139. #define        RSkipPixels(n)        mk_inst_1(RSkipPixelsOp,(n))
  140.  
  141. #define        RNewLine            RSkipLines(1)
  142.  
  143. #define        RByteData(n)        mk_inst_1(RByteDataOp,n)
  144.                     /* followed by ((n+1)/2)*2 bytes */
  145.                     /* of data.  If n is odd, last */
  146.                     /* byte will be ignored */
  147.                     /* "cursor" is left at pixel */
  148.                     /* following last pixel written */
  149.  
  150. #define        RRunData(n,c)        mk_inst_2(RRunDataOp,(n),(c))
  151.                     /* next word contains color data */
  152.                     /* "cursor" is left at pixel after */
  153.                     /* end of run */
  154.  
  155. #define     REOF            mk_inst_1(REOFOp,0)
  156.                     /* Really opcode only */
  157.  
  158. extern char *vax_pshort();
  159.  
  160. /*****************************************************************
  161.  * TAG( RunSetup )
  162.  * Put out initial setup data for RLE files.
  163.  */
  164. void
  165. RunSetup(the_hdr)
  166. register rle_hdr * the_hdr;
  167. {
  168.     struct XtndRsetup setup;
  169.     register FILE * rle_fd = the_hdr->rle_file;
  170.  
  171.     put16( RLE_MAGIC );
  172.  
  173.     if ( the_hdr->background == 2 )
  174.     setup.h_flags = H_CLEARFIRST;
  175.     else if ( the_hdr->background == 0 )
  176.     setup.h_flags = H_NO_BACKGROUND;
  177.     else
  178.     setup.h_flags = 0;
  179.     if ( the_hdr->alpha )
  180.     setup.h_flags |= H_ALPHA;
  181.     if ( the_hdr->comments != NULL && *the_hdr->comments != NULL )
  182.     setup.h_flags |= H_COMMENT;
  183.  
  184.     setup.h_ncolors = the_hdr->ncolors;
  185.     setup.h_pixelbits = 8;        /* Grinnell dependent */
  186.     if ( the_hdr->ncmap > 0 && the_hdr->cmap == NULL )
  187.     {
  188.     fprintf( stderr,
  189.        "%s: Color map of size %d*%d specified, but not supplied, writing %s\n",
  190.          the_hdr->cmd, the_hdr->ncmap, (1 << the_hdr->cmaplen),
  191.          the_hdr->file_name );
  192.     the_hdr->ncmap = 0;
  193.     }
  194.     setup.h_cmaplen = the_hdr->cmaplen;    /* log2 of color map size */
  195.     setup.h_ncmap = the_hdr->ncmap;    /* no of color channels */
  196.     vax_pshort(setup.hc_xpos,the_hdr->xmin);
  197.     vax_pshort(setup.hc_ypos,the_hdr->ymin);
  198.     vax_pshort(setup.hc_xlen,the_hdr->xmax - the_hdr->xmin + 1);
  199.     vax_pshort(setup.hc_ylen,the_hdr->ymax - the_hdr->ymin + 1);
  200.     fwrite((char *)&setup, SETUPSIZE, 1, rle_fd);
  201.     if ( the_hdr->background != 0 )
  202.     {
  203.     register int i;
  204.     register rle_pixel *background =
  205.         (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
  206.     register int *bg_color;
  207.     /* 
  208.      * If even number of bg color bytes, put out one more to get to 
  209.      * 16 bit boundary.
  210.      */
  211.     bg_color = the_hdr->bg_color;
  212.     for ( i = 0; i < the_hdr->ncolors; i++ )
  213.         background[i] =  *bg_color++;
  214.     /* Extra byte, if written, should be 0. */
  215.     background[i] = 0;
  216.     fwrite((char *)background, (the_hdr->ncolors / 2) * 2 + 1, 1, rle_fd);
  217.     free( background );
  218.     }
  219.     else
  220.     putc( '\0', rle_fd );
  221.     if (the_hdr->ncmap > 0)
  222.     {
  223.     /* Big-endian machines are harder */
  224.     register int i, nmap = (1 << the_hdr->cmaplen) *
  225.                    the_hdr->ncmap;
  226.     register char *h_cmap = (char *)malloc( nmap * 2 );
  227.     if ( h_cmap == NULL )
  228.     {
  229.         fprintf( stderr,
  230.          "%s: Malloc failed for color map of size %d, writing %s\n",
  231.              the_hdr->cmd, nmap, the_hdr->file_name );
  232.         exit( 1 );
  233.     }
  234.     for ( i = 0; i < nmap; i++ )
  235.         vax_pshort( &h_cmap[i*2], the_hdr->cmap[i] );
  236.  
  237.     fwrite( h_cmap, nmap, 2, rle_fd );
  238.     free( h_cmap );
  239.     }
  240.  
  241.     /* Now write out comments if given */
  242.     if ( setup.h_flags & H_COMMENT )
  243.     {
  244.     int comlen;
  245.     register CONST_DECL char ** com_p;
  246.  
  247.     /* Get the total length of comments */
  248.     comlen = 0;
  249.     for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
  250.         comlen += 1 + strlen( *com_p );
  251.  
  252.     put16( comlen );
  253.     for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
  254.         fwrite( *com_p, 1, strlen( *com_p ) + 1, rle_fd );
  255.  
  256.     if ( comlen & 1 )    /* if odd length, round up */
  257.         putc( '\0', rle_fd );
  258.     }
  259. }
  260.  
  261. /*****************************************************************
  262.  * TAG( RunSkipBlankLines )
  263.  * Skip one or more blank lines in the RLE file.
  264.  */
  265. void
  266. RunSkipBlankLines(nblank, the_hdr)
  267. int nblank;
  268. register rle_hdr * the_hdr;
  269. {
  270.     register FILE * rle_fd = the_hdr->rle_file;
  271.     RSkipLines(nblank);
  272. }
  273.  
  274. /*****************************************************************
  275.  * TAG( RunSetColor )
  276.  * Select a color and do carriage return.
  277.  * color: 0 = Red, 1 = Green, 2 = Blue.
  278.  */
  279. void
  280. RunSetColor(c, the_hdr)
  281. int c;
  282. register rle_hdr * the_hdr;
  283. {
  284.     register FILE * rle_fd = the_hdr->rle_file;
  285.     RSetColor(c);
  286. }
  287.  
  288. /*****************************************************************
  289.  * TAG( RunSkipPixels )
  290.  * Skip a run of background.
  291.  */
  292.  
  293. /* ARGSUSED */
  294. void
  295. RunSkipPixels(nskip, last, wasrun, the_hdr)
  296. int nskip, last, wasrun;
  297. register rle_hdr * the_hdr;
  298. {
  299.     register FILE * rle_fd = the_hdr->rle_file;
  300.     if (! last && nskip > 0)
  301.     {
  302.     RSkipPixels(nskip);
  303.     }
  304. }
  305.  
  306. /*****************************************************************
  307.  * TAG( RunNewScanLine )
  308.  * Perform a newline action.  Since CR is implied by the Set Color
  309.  * operation, only generate code if the newline flag is true.
  310.  */
  311. void
  312. RunNewScanLine(flag, the_hdr)
  313. int flag;
  314. register rle_hdr * the_hdr;
  315. {
  316.     register FILE * rle_fd = the_hdr->rle_file;
  317.     if (flag)
  318.     {
  319.     RNewLine;
  320.     }
  321. }
  322.  
  323. /*****************************************************************
  324.  * TAG( Runputdata )
  325.  * Put one or more pixels of byte data into the output file.
  326.  */
  327. void
  328. Runputdata(buf, n, the_hdr)
  329. rle_pixel * buf;
  330. int n;
  331. register rle_hdr * the_hdr;
  332. {
  333.     register FILE * rle_fd = the_hdr->rle_file;
  334.     if (n == 0)
  335.     return;
  336.  
  337.     RByteData(n-1);
  338.     fwrite((char *)buf, n, 1, rle_fd);
  339.     if ( n & 1 )
  340.     putc( 0, rle_fd );
  341. }
  342.  
  343. /*****************************************************************
  344.  * TAG( Runputrun )
  345.  * Output a single color run.
  346.  */
  347.  
  348. /* ARGSUSED */
  349. void
  350. Runputrun(color, n, last, the_hdr)
  351. int color, n, last;
  352. register rle_hdr * the_hdr;
  353. {
  354.     register FILE * rle_fd = the_hdr->rle_file;
  355.     RRunData(n-1,color);
  356. }
  357.  
  358.  
  359. /*****************************************************************
  360.  * TAG( RunputEof )
  361.  * Output an EOF opcode
  362.  */
  363. void
  364. RunputEof( the_hdr )
  365. register rle_hdr * the_hdr;
  366. {
  367.     register FILE * rle_fd = the_hdr->rle_file;
  368.     REOF;
  369. }
  370.